﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Hx.Sdk.Core.FriendlyException
{
    /// <summary>
    /// 错误页面
    /// </summary>
    public class BadPageResult : StatusCodeResult
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public BadPageResult()
            : base(400)
        {
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="statusCode">状态码</param>
        public BadPageResult(int statusCode)
            : base(statusCode)
        {
        }

        /// <summary>
        /// 标题
        /// </summary>
        public string Title { get; set; } = "ModelState Invalid";

        /// <summary>
        /// 描述
        /// </summary>
        public string Description { get; set; } = "User data verification failed. Please input it correctly.";

        /// <summary>
        /// 图标
        /// </summary>
        /// <remarks>必须是 base64 类型</remarks>
        public string Base64Icon { get; set; } = "";

        /// <summary>
        /// 错误代码
        /// </summary>
        public string Code { get; set; } = "";

        /// <summary>
        /// 错误代码语言
        /// </summary>
        public string CodeLang { get; set; } = "json";

        /// <summary>
        /// 返回通用 401 错误页
        /// </summary>
        public static BadPageResult Status401Unauthorized => new(StatusCodes.Status401Unauthorized)
        {
            Title = "401 Unauthorized",
            Code = "401 Unauthorized",
            Description = "",
            CodeLang = "txt"
        };

        /// <summary>
        /// 返回通用 403 错误页
        /// </summary>
        public static BadPageResult Status403Forbidden => new(StatusCodes.Status403Forbidden)
        {
            Title = "403 Forbidden",
            Code = "403 Forbidden",
            Description = "",
            CodeLang = "txt"
        };

        /// <summary>
        /// 返回通用 404 错误页
        /// </summary>
        public static BadPageResult Status404NotFound => new(StatusCodes.Status404NotFound)
        {
            Title = "404 Not Found",
            Code = "404 Not Found",
            Description = "",
            CodeLang = "txt"
        };

        /// <summary>
        /// 返回通用 500 错误页
        /// </summary>
        public static BadPageResult Status500InternalServerError => new(StatusCodes.Status500InternalServerError)
        {
            Title = "500 Internal Server Error",
            Code = "500 Internal Server Error",
            Description = "",
            CodeLang = "txt"
        };

        /// <summary>
        /// 重写返回结果
        /// </summary>
        /// <param name="context"></param>
        public override void ExecuteResult(ActionContext context)
        {
            base.ExecuteResult(context);

            var httpContext = context.HttpContext;

            // 如果 Response 已经完成输出或 WebSocket 请求，则禁止写入
            if (httpContext.IsWebSocketRequest() || httpContext.Response.HasStarted) return;
            httpContext.Response.Body.WriteAsync(ToByteArray());
        }

        /// <summary>
        /// 将 <see cref="BadPageResult"/> 转换成字符串
        /// </summary>
        /// <returns><see cref="string"/></returns>
        public override string ToString()
        {
            // 获取当前类型信息
            var thisType = typeof(BadPageResult);
            var thisAssembly = thisType.Assembly;
            // 读取嵌入式页面路径
            var errorhtml = $"{thisAssembly.GetName().Name}{thisType.Namespace.Replace("Hx", string.Empty)}.Assets.error.html";

            // 解析嵌入式文件流
            byte[] buffer;
            using (var readStream = thisAssembly.GetManifestResourceStream(errorhtml))
            {
                buffer = new byte[readStream.Length];
                readStream.Read(buffer, 0, buffer.Length);
            }

            // 读取内容并替换
            var content = Encoding.UTF8.GetString(buffer);
            content = content.Replace($"@{{{nameof(Title)}}}", Title)
            .Replace($"@{{{nameof(Description)}}}", Description)
            .Replace($"@{{{nameof(StatusCode)}}}", StatusCode.ToString())
                             .Replace($"@{{{nameof(Code)}}}", Code)
                             .Replace($"@{{{nameof(CodeLang)}}}", CodeLang)
                             .Replace($"@{{{nameof(Base64Icon)}}}", Base64Icon);

            return content;
        }

        /// <summary>
        /// 将 <see cref="BadPageResult"/> 转换成字节数组
        /// </summary>
        /// <returns><see cref="byte"/></returns>
        public byte[] ToByteArray()
        {
            return Encoding.UTF8.GetBytes(ToString());
        }
    }
}
